package com.zmn.oms.task.ins;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.oms.common.constant.InsConsts;
import com.zmn.oms.common.utils.HttpUtil;
import com.zmn.oms.model.entity.ins.InsOrderMasterCpic;
import com.zmn.oms.model.entity.ins.InsOrderSync;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.format.annotation.DateTimeFormat;

import java.util.*;

/**
 * 类描述：
 *
 * @author lhl
 * @date 2021/02/07 16:14
 */
@Slf4j
public class CpicInsSyncInvoker {
    //private static String key = "6BDBF0E1-BE58-4DAB-AF38-A263303D538D";
    //private static String syncUrl = "https://cxcq.cpic.com.cn/shsjk/zmn_data.ashx";

    public static ResponseData syncData(List<InsOrderSync> dataList) {
        List<InsOrderSyncDTO> list = BeanMapper.mapList(dataList, InsOrderSyncDTO.class);
        String data = JSON.toJSONString(list);
        String tjtime = DateUtil.toString(new Date(), DateUtil.FORMAT_DEFAULT);

        RequestData params = new RequestData();
        params.setType("pddata_receive");
        params.setData(data);
        params.setTjtime(tjtime);
        params.setVerifycode(sign(params.getType(), data, tjtime));

        ResponseData response = null;
        try {
            boolean isHttps = InsConsts.CPIC_SYNC_URL.toLowerCase().startsWith("https://");
            String requestStr = JSON.toJSONString(params);
            String url = InsConsts.CPIC_SYNC_URL;

            log.info("【同步按单保险】-Request: url=[{}], params=[{}]", url, requestStr);
            String responseStr = isHttps ? HttpUtil.httpsPost(url, requestStr) : HttpUtil.httpPost(url, requestStr);
            log.info("【同步按单保险】-Response: response=[{}]", responseStr);
            response = JSON.parseObject(responseStr, ResponseData.class);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            response = new ResponseData();
            response.setStatus(ResponseData.STATUS_FAIL);
            response.setErrmsg(e.getMessage());
        }

        return response;
    }


    public static InsureResponse syncInsureData(List<InsOrderMasterCpic> dataList) {
        InsureResponse response = null;

        Map<String, Object> params = new HashMap();
        String requestId = null;
        String insStartDate = null;
        String insEndDate = null;
        {
            Date time = DateUtil.addMinute(new Date(), 10);
            insStartDate = DateUtil.toString(time);
            insEndDate = DateUtil.toString(DateUtil.addDays(time, 1));
        }
        {
            // head
            InsureRequestHead head = new InsureRequestHead(InsConsts.CPIC_INSURE_APPID);
            head.generateMd5Value(InsConsts.CPIC_INSURE_SECRETKEY);
            requestId = head.getRequestId();
            params.put("head", head);
            // body
            Map<String, Object> body = new HashMap();
            body.put("insuInfos", getInsuInfos(dataList, insStartDate, insEndDate));
            body.put("responseUrl", InsConsts.CPIC_INSURE_CALLBACK_URL);
            params.put("body", body);
        }
        String url = String.format("%s%s%s",
                InsConsts.CPIC_INSURE_URL,
                InsConsts.CPIC_INSURE_URL.endsWith("/") ? "" : "/",
                "apiOpen/md5/apiInsu"
        );

        try {
            boolean isHttps = InsConsts.CPIC_INSURE_URL.toLowerCase().startsWith("https://");
            String requestStr = JSON.toJSONString(params);

            log.info("【给工程师买保险】-Request: requestId=[{}], url=[{}], params=[{}]", requestId, url, requestStr);
            String responseStr = isHttps ? HttpUtil.httpsPost(url, requestStr) : HttpUtil.httpPost(url, requestStr);
            log.info("【给工程师买保险】-Response: requestId=[{}], response=[{}]", requestId, responseStr);

            response = JSON.parseObject(responseStr, InsureResponse.class);
            response.setInsStartDate(insStartDate);
            response.setInsEndDate(insEndDate);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            response = new InsureResponse();
            response.setResultCode(InsureResponse.STATUS_FAIL);
            response.setResultMessage(e.getMessage());
        }

        return response;
    }

    public static InsureResponse queryInsureData(String requestId) {
        InsureResponse response = null;

        Map<String, Object> params = new HashMap();
        {
            // head
            InsureRequestHead head = new InsureRequestHead(InsConsts.CPIC_INSURE_APPID);
            head.generateMd5Value(InsConsts.CPIC_INSURE_SECRETKEY);
            params.put("head", head);
            // body
            Map<String, Object> body = new HashMap();
            body.put("requestId", requestId);
            params.put("body", body);
        }
        String url = String.format("%s%s%s",
                InsConsts.CPIC_INSURE_URL,
                InsConsts.CPIC_INSURE_URL.endsWith("/") ? "" : "/",
                "apiOpen/md5/queryMore"
        );

        try {
            boolean isHttps = InsConsts.CPIC_INSURE_URL.toLowerCase().startsWith("https://");
            String requestStr = JSON.toJSONString(params);

            log.info("【查询保险出单】-Request: url=[{}], params=[{}]", url, requestStr);
            String responseStr = isHttps ? HttpUtil.httpsPost(url, requestStr) : HttpUtil.httpPost(url, requestStr);
            log.info("【查询保险出单】-Response: requestId=[{}], response=[{}]", requestId, responseStr);

            response = JSON.parseObject(responseStr, InsureResponse.class);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            response = new InsureResponse();
            response.setResultCode(InsureResponse.STATUS_FAIL);
            response.setResultMessage(e.getMessage());
        }

        return response;
    }

    /**
     * 生成verifycode（MD5验证码）
     * 验证规则：
     *  1. tjtime与同步时间差不能超过10分钟;
     *  2. verifycode 生成规则:type + key + data + tjtime拼接成字符串，获取md5验证码；
     * @return
     */
    private static String sign(String type, String data, String tjtime) {
        StringBuilder signBuilder = new StringBuilder();
        signBuilder.append(type)
                .append(InsConsts.CPIC_SYNC_KEY)
                .append(data)
                .append(tjtime);

        String verifycode = DigestUtils.md5Hex(signBuilder.toString());
        return verifycode;
    }

    /**
     * 同步保险信息请求参数
     */
    @Data
    public static class RequestData {
        private String type;        // 接口类型值，使用固定值: pddata_receive
        private String data;        // 保险数据，json数组格式
        private String tjtime;      // 提交时间，格式:yyyy-mm-dd HH:mm:ss
        private String verifycode;  // MD5验证码
    }
    /**
     * 同步保险信息响应参数
     */
    @Data
    public static class ResponseData {
        public static final String STATUS_FAIL = "000";     // 失败
        public static final String STATUS_SUCCESS = "001";  // 成功

        private String status;      // 状态吗[000:失败  001：成功]
        private String errmsg;      // 错误信息

        public boolean isSuccess() {
            return STATUS_SUCCESS.equals(status);
        }
    }

    /**
     * 推送用保险数据模型
     */
    @Data
    public static class InsOrderSyncDTO {
        /**
         * 工单号
         */
        private String code;
        /**
         * 订单类型：0 新单、1 返修
         */
        private Integer type;
        /**
         * 品类名称
         */
        private String categoryName;
        /**
         * 0：开始 1：结束
         */
        private Integer status;
        /**
         * 开始或结束时间
         */
        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        @JSONField(format = "yyyy-MM-dd HH:mm:ss")
        private Date time;
        /**
         * 工程师名称
         */
        private String servicemanName;
        /**
         * 工程师身份证号
         */
        private String servicemanCardNo;
        /**
         * 城市ID
         */
        private String cityId;
        /**
         * 城市名称
         */
        private String cityName;
        /**
         * 用户地址
         */
        private String address;
        /**
         * 添加时间
         */
        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        @JSONField(format = "yyyy-MM-dd HH:mm:ss")
        private Date createdOn;
    }


    @Data
    public static class InsureRequestHead {
        private String requestId;
        private String appId;
        // 格式为：yyyy-MM-dd HH:mm:ss
        private String sendTime;
        private String productCode; // 意外险
        private String md5Value;


        public void generateMd5Value(String key) {
            StringBuilder sb = new StringBuilder();
            sb.append(this.requestId)
                    .append(this.appId)
                    .append(this.productCode)
                    .append(key);
            String md5 = DigestUtils.md5Hex(sb.toString());
            this.md5Value = md5;
        }

        public InsureRequestHead() {}

        public InsureRequestHead(String appId) {
            this.requestId = UUID.randomUUID().toString().replaceAll("-", "");
            this.productCode = "02010000006";
            this.sendTime = DateUtil.getNowFormatted();
            this.appId = appId;
        }
    }

    @Data
    public static class InsureResponse {
        public static final String STATUS_FAIL = "-1";      // 失败
        public static final String STATUS_SUCCESS = "1";    // 成功

        private String resultCode;      // 状态吗[-1:失败  1：成功]
        private String success;         // true 成功 false 失败

        private String resultMessage;      // 错误信息
        private String data;      // 请求requestId

        private String insStartDate;
        private String insEndDate;

        public boolean isSuccess() {
            return STATUS_SUCCESS.equals(resultCode);
        }
    }

    public static List<Map<String, Object>> getInsuInfos(List<InsOrderMasterCpic> dataList,
                                                         String insStartDate, String insEndDate) {
        List<Map<String, Object>> insuInfos = new ArrayList<>(dataList.size());

        for (InsOrderMasterCpic item : dataList) {
            Map<String, Object> map = new HashMap<>();
            insuInfos.add(map);

            map.put("schemaCode", item.getSchemaCode());
            map.put("insuApplicant", "重庆啄木鸟网络科技有限公司");
            map.put("insuApplicantIdentityType", "204");
            map.put("insuApplicantIdentityNo", "915000003204475734");
            map.put("insuApplicantPhone", "15310684686");
            map.put("insStartDate", insStartDate);
            map.put("insEndDate", insEndDate);
            map.put("extAttr", String.valueOf(item.getInsMasterId()));

            List<Map<String, String>> masterList = new LinkedList<Map<String, String>>();
            map.put("insuredList", masterList);
            Map<String, String> master = new HashMap<>();
            masterList.add(master);

            master.put("insured", item.getMasterName());
            master.put("insuredIdentityType", "101"); // 身份证:101
            master.put("insuredIdentityNo", item.getMasterCardNo());
        }

        return insuInfos;
    }

       public static void main(String[] args) {
        InsConsts.CPIC_INSURE_URL = "http://test.fastins.cn:9090/";
        InsConsts.CPIC_INSURE_APPID = "zmn";
        InsConsts.CPIC_INSURE_SECRETKEY = "15a9dec4-8107-11e7-97dm-3f7db41137g2";
        InsConsts.CPIC_INSURE_CALLBACK_URL = "http://test2-api-oms.xiujiadian.com/ins/cpic/pushInsureds";

/*        List<InsOrderMasterCpic> list = new LinkedList<>();
        for (int i=0,len=1; i<len; i++) {
            InsOrderMasterCpic item = new InsOrderMasterCpic();
            list.add(item);

            item.setSchemaCode("P23C198002100000123");
            item.setInsStartDate("2021-03-30 00:00:00");
            item.setInsEndDate("2021-04-29 00:00:00");
            item.setInsMasterId(100000L);
            item.setMasterName("赵周测试三");
            item.setMasterCardNo("133333333333333333");
        }

        syncInsureData(list);*/

           //queryInsureData("db8b5de0bd55437ca784584c8b423fbd");

           String json = "{\"resultCode\": 1,\"resultMessage\": \"\",\"data\": {\"insuredList\": [{\"insured\": \"测试\",\"insuredIdentityNo\": \"610524***3244\",\"requestId\": \"663a4050025a4acf8d0099b097d26fb8\",\"insureNo\": \"ACHQ669E0221PAAAAAA5\",\"formStatus\": 8}],\"insuApplicantIdentityNo\": \"610524***3244\",\"insuApplicant\": \"测试\",\"formStatus\": 8,\"insEndDate\": \"2021-03-10\",\"insStartDate\": \"2021-03-09\"},\"data2\": null,\"data3\": null,\"mapData\": {},\"success\": true,\"failed\": false}";
           InsureResponse response = JSON.parseObject(json, InsureResponse.class);

           System.out.println(JSON.toJSONString(response));

    }
}
